/****************/
/* Jiahui Shi	*/
/* 05/28/2011	*/
/* CS 244B	*/
/* Spring 2011	*/
/****************/

#define DEBUG

#include "server.h"

/* ------------------------------------------------------------------ */


int
main(int argc, char *argv[]) {
  int portNum = 44038;
  server_in_use = 0;
  if (argc < 5) {
    strcpy(filename, "~/dfsmount/");
  }
  else {
  }
  netInit(&myAddr, &my_socket, &groupAddr, portNum);
  myIP = myAddr.sin_addr.s_addr;
  printf("my IP: %d   mount addr: %s\n", myIP, filename);
  
  MWEvent event;
  ShortPacket incoming;
  event.eventDetail = (ShortPacket*)&incoming;
  
  while (1) {
    NextEvent(&event, my_socket);
    processPacket(&event);
  }
  return 0;
}

void sendNoPayloadPack(uint32_t type)
{
  ShortPacket pack;
  
  pack.header.type = type;
  pack.header.paylen = 0;
  
  sendShortPacket(pack);
}

void sendShortPacket(ShortPacket pack)
{
  static uint32_t my_seqnum = 0;
  pack.header.seqnum = my_seqnum;

  fillChecksum((LongPacket*)&pack);
//   ConvertOutgoing(&pack);
  
  if (sendto(my_socket, &pack, sizeof(pack), 0,
	      (struct sockaddr*) &groupAddr, sizeof(Sockaddr)) < 0)
    { MWError("Sample error"); }
  my_seqnum++;
}

void processPacket (MWEvent *eventPacket)
{
  in_addr_t senderIP = eventPacket->eventSource.sin_addr.s_addr;
  printf("receive from ip: %d\n", senderIP);
  ShortPacket *pack = eventPacket->eventDetail;

  if (!checkSumRight(*pack)) return;
  if (server_in_use && (senderIP != clientIP)) return; // not my client
  if (!server_in_use && (pack->header.type != ADD_SERVER_REQUEST_TYPE)) return; //only expecting Add_Server
  
  switch(pack->header.type) {
	case ADD_SERVER_REQUEST_TYPE: {
	  if (server_in_use) break;
	  AddServerRequestPack *packX = (AddServerRequestPack *) &pack->body;
	  if (packX->ip == myIP) {
	    clientIP = senderIP;
	    Sockaddr in;
	    in.sin_addr.s_addr = clientIP;
	    
//   printf("add client: %d\n", clientIP);
  printf("add client: %s\n", inet_ntoa(in.sin_addr));
	    server_in_use = 1;
	    sendNoPayloadPack(ADD_SERVER_RESPONSE_TYPE);
	  }
	  break;
	}
// 	
// 	case JOIN_RESPONSE_TYPE:
// 	{
// 	  JoinResponsePack *packX = (JoinResponsePack *) &pack->body;
// 	  
// 	  if (idExist(senderid) || (packX->target_id != M->myId_)) break; // already in list
// 	  
// 	  // add this responder into my rat list
// 	  if (addRat(pack->id, packX->name, pack->seqnum))
// 	  {
// 	    int newid = lookupRatId(pack->id);
// 	    uint16_t x,y,d;
// 	    getX_Y_D(packX -> xyd, x, y, d);
// 	    SetRatPosition(RatIndexType(newid), x, y, d);
// 	    M->scores_[newid] = packX->score;
// 	    joining[newid] = true;
// 	  }
// 	  break;
// 	}
// 	
// 	case UPDATE_TYPE:
// 	{
// 	  UpdatePack *packX = (UpdatePack *) &pack->body;
// 	  if (senderid < 0) break;
// 	  if(!M->rat(RatIndexType(senderid)).playing) 
// 	    if (joining[senderid]) joining[senderid] = false;
// 	    else break;
// 	  
// 	  // update the state of this responder in my rat list
// 	  uint16_t x,y,d;
// 	  getX_Y_D(packX -> xyd, x, y, d);
// 	  M->scores_[senderid] = packX->score;
// 	  UpdateScoreCard(RatIndexType(senderid));
// 	  if (sqOccupied(senderid, Loc(x), Loc(y)) < 0)
// 	    SetRatPosition(RatIndexType(senderid), x, y, d);
// 	  Rats2Display[senderid].visible = true;
// 	  
// 	  if ((x == M->xtag.value())&&(y == M->ytag.value())) hit = senderid;
// 	  break;
// 	}
// 	  
// 	case TAG_TYPE:
// 	{
// 	  TagPack *packX = (TagPack *) &pack->body;
// 	  if (!idExist(senderid)) break;
// 	  if (packX->target_id == M->myId_)
// 	  {
// 	    // check replicated tag packet
// 	    if ((lastAttackerId == pack->id) && abs((int)lastAttackSeqnum - (int)pack->seqnum) <= 5) break;
// 	    lastAttackerId = pack->id;
// 	    lastAttackSeqnum = pack->seqnum;
// 	    
// 	    NewPosition(M);
// 	    M->scoreIs(M->score().value()-5);
// 	    sendTagResponsePack(pack->id);
// 	    
// 	    UpdateScoreCard(RatIndexType(MY_RAT_INDEX));
// 	  }
// 	  break;
// 	}
// 	
// 	case TAG_RESPONSE_TYPE:
// 	{	  
// 	  TagResponsePack *packX = (TagResponsePack *) &pack->body;
// 	  if (!idExist(senderid)) break;
// 	  
// 	  // update the state of this responder in my rat list
// 	  uint16_t x,y,d;
// 	  getX_Y_D(packX -> xyd, x, y, d);
// 	  if (sqOccupied(senderid, Loc(x), Loc(y)) < 0)
// 	    SetRatPosition(RatIndexType(senderid), x, y, d);
// 	  M->scores_[senderid] = packX->score;
// 	  UpdateScoreCard(RatIndexType(senderid));
// 	  Rats2Display[senderid].visible = true;
// 	  
// 	  if (packX->attacker_id == M->myId_) 
// 	  {
// 	    tagDone[senderid] = true;
// 	    M->scoreIs(M->score().value()+11);
// 	    UpdateScoreCard(RatIndexType(MY_RAT_INDEX));
// 	    sendUpdatePack();
// 	  }
// 	  break;
// 	}
// 	
// 	case FINISH_TYPE:
// 	{
// 	  if (!idExist(senderid)) break;
// 	  removeRat(RatIndexType(senderid));
// 	  break;
// 	}
	default: break;
  }
}

